package nig.mf.plugin.sink;

import arc.mf.plugin.DataSinkImpl;
import arc.mf.plugin.PluginLog;
import arc.mf.plugin.sink.ParameterDefinition;
import arc.streams.LongInputStream;
import arc.xml.XmlDoc.Element;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;


/**
 * A custom sink that simply logs all calls to
 * {@link #beginMultiple(java.util.Map)},
 * {@link #endMultiple(java.lang.Object)},
 * {@link #consume(java.lang.Object, java.util.Map, java.lang.String,
 *                 arc.xml.XmlDoc.Element, arc.xml.XmlDoc.Element,
 *                 arc.streams.LongInputStream,java.lang.String,
 *                 java.lang.String, long)}
 * and {@link #shutdown()}.
 * 
 * @author King Lung Chiu
 */
public class LoggingSink implements DataSinkImpl
{
   private final SinkLogger logger = new SinkLogger(this.getClass().getCanonicalName());


	@Override public String[]  acceptedTypes() throws Throwable { return null; }
	@Override public int       compressionLevelRequired()       { return -1; }
	@Override public String    description() throws Throwable   { return "Logging Sink 0.0.1"; }
	@Override public String    type() throws Throwable          { return "logsink"; }
	@Override public Map<String, ParameterDefinition> parameterDefinitions() throws Throwable {
		return RemoteSinkParam.definitions();
	}

   @Override
   public Object beginMultiple(Map<String, String> params) throws Throwable {
      return logger.beginMultiple(params);
   }
   @Override
   public void endMultiple(Object ctxKey) throws Throwable {
      logger.endMultiple(ctxKey);
   }
	@Override
	public void shutdown() throws Throwable {
      logger.shutdown();
	}
	@Override
	public void consume(
      Object multiCtx,
      String path,
      Map<String, String> params,
      Element userMeta,
      Element meta,
      LongInputStream in,
      String appMimeType,
      String streamMimeType,
      long length
   ) throws Throwable {
      logger.consume(
         multiCtx, path, params, userMeta, meta,
         in, appMimeType, streamMimeType, length);
      Throwable error = null;
      
      StringBuilder msg = new StringBuilder("\n")
         .append(this.getClass().getSimpleName())
         .append(".consume(Object multiCtx, String path, Map<String, String> params, Element userMeta, Element meta, LongInputStream in, String appMimeType, String streamMimeType)");
      
      try {
//         RemoteSinkParam host = RemoteSinkParam.host;
//         boolean exists = host.existsIn(params);
         msg.append("\n-- filePath        : ");
         if(!RemoteSinkParam.path.existsIn(params)) {
            msg.append("indeterminant: no path supplied !!!!!!!!!!!!!!!!!!!!\n");
         } else {
            final String baseDir = RemoteSinkParam.path.from(params);
            final String filePath =
               (baseDir + "/" + path).replace("\\\\", "/").replace("\\", "/");
            msg.append(filePath);

            final File f = new File(filePath);
            final File p = f.getParentFile();
            if(!p.exists() && !p.mkdirs()) {
               msg.append("\n                     ERROR: unable to create parent folders !!!!!!!!!!!!!");
               // logger.log(PluginLog.INFORMATION, msg.toString());
               throw new IllegalArgumentException(
                  "unable to create parent folders at " + p.getAbsolutePath());
            }

            FileOutputStream fos = new FileOutputStream(filePath);
            byte[] buff = new byte[1024 * 10];
            int size = in.read(buff);
            while(size > 0) {
              fos.write(buff, 0, size);
              size = in.read(buff);
            }
            fos.close();
            in.close();
            msg.append("\n                     ... written to file");
         }
         
         
         
      } catch(Throwable t) {
         msg.append("\n!!! Unexpected error occurred !!!");
         error = t;
      }
      msg.append("\n\n");
      
      if(error != null) {
         logger.log(PluginLog.INFORMATION, msg.toString(), error);
      } else {
         logger.log(PluginLog.INFORMATION, msg.toString());
         
       
        
      }
      
//      if(streamMimeType == null || !ArchiveRegistry.isAnArchive(streamMimeType)) {
//         
//      } else {
//         
//      }
	}
}
